package com.one.blocks.rbac.config;

import com.one.blocks.rbac.controller.valid.NoAllocatedData;
import com.one.blocks.rbac.controller.valid.NoAllocatedDataValidatorForInteger;
import com.one.blocks.rbac.controller.valid.NoAllocatedDataValidatorForIntegerSet;
import com.one.blocks.rbac.controller.valid.ValidTree;
import com.one.blocks.rbac.controller.valid.ValidTreeValidatorForSysMenu;
import com.one.blocks.rbac.controller.valid.ValidTreeValidatorForSysOrg;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.HibernateValidatorConfiguration;
import org.hibernate.validator.cfg.ConstraintMapping;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.ArrayList;
import java.util.List;

/**
 * @author <a href="mailto:idler41@163.com">linfuxin</a> created by 2022-12-11 15:01:33
 */
public class HibernateValidatorSupport {

    @Bean
    public Validator validator(AutowireCapableBeanFactory springFactory) {
        HibernateValidatorConfiguration configuration = Validation.byProvider(HibernateValidator.class).configure();

        for (ConstraintMapping mapping : addConstraintMapping(configuration)) {
            configuration.addMapping(mapping);
        }
        try (ValidatorFactory factory = configuration
                .failFast(true)
                // 解决 SpringBoot 依赖注入问题
                .constraintValidatorFactory(new SpringConstraintValidatorFactory(springFactory))
                .buildValidatorFactory()
        ) {
            return factory.getValidator();
        }
    }

    protected List<ConstraintMapping> addConstraintMapping(HibernateValidatorConfiguration configuration) {
        List<ConstraintMapping> constraintMappingSet = new ArrayList<>();
        ConstraintMapping noAllocatedDataConstraintMapping = configuration.createConstraintMapping();
        noAllocatedDataConstraintMapping
                .constraintDefinition(NoAllocatedData.class)
                .validatedBy(NoAllocatedDataValidatorForIntegerSet.class)
                .validatedBy(NoAllocatedDataValidatorForInteger.class)
//                .validatedBy(NoAllocatedDataValidatorForSysMenu.class)
//                .validatedBy(NoAllocatedDataValidatorForSysOrg.class)
                .includeExistingValidators(true);

        ConstraintMapping treeStructConstraintMapping = configuration.createConstraintMapping();
        treeStructConstraintMapping
                .constraintDefinition(ValidTree.class)
                .validatedBy(ValidTreeValidatorForSysMenu.class)
                .validatedBy(ValidTreeValidatorForSysOrg.class)
                .includeExistingValidators(true);

        constraintMappingSet.add(noAllocatedDataConstraintMapping);
        constraintMappingSet.add(treeStructConstraintMapping);

        return constraintMappingSet;
    }
}
